$def with (page, edition=None)

$ is_privileged_user = ctx.user and (ctx.user.is_admin() or ctx.user.is_super_librarian())
$ is_librarian = ctx.user and ctx.user.is_librarian()

$ component_times = {}
$ component_times['TotalTime'] = time()

$ tab = input(tab=None).tab
$ editions = []
$ page_type = page.key.split('/')[1]
$ show_observations = True

$if page.key.startswith('/works'):
  $ work = page
$elif page.works:
  $ work = list(page.works)[0]
$else:
  $ work = page.make_work_from_orphaned_edition()
  $ show_observations = False

$# This can happen when looking at past versions of an edition who's work
$# has since been merged.
$if work.type.key == '/type/redirect':
  $ redir = work
  $ work = get_document(redir.key)
  $ work['title'] = '↪ ' + redir.key

$ edition = storage({})
$if query_param('edition', '').startswith('key:'):
  $ edition = get_type(query_param('edition', '').split(':')[1])
$elif page.key.startswith('/books'):
  $# We are on an editions page: an edition has been explicitly selected
  $ edition = page

$ selected_provider = None
$ selected_id = None
$ provider = None
$if query_param('edition') and not edition:
  $if ':' in query_param('edition'):
    $ [selected_provider, selected_id] = query_param('edition').split(':')
  $else:
    $ [selected_provider, selected_id] = ['ia', query_param('edition')]
  $ provider = get_book_provider_by_name(selected_provider)

$ component_times['get_sorted_editions'] = time()

$# Fetch a work's editions
$# Used for loading the editions table
$# Book availability of editions injected by bulk get_availability API
$ edition_count = work.edition_count if work and work.edition_count else 1
$ ebooks_only = (query_param('mode') == 'ebooks') or (query_param('mode') != 'all' and edition_count > 10)

$# For performance reasons, limit to 10 ebooks
$# Tradeoff: limits our ability to select best edition
$ editions_limit = None if query_param('mode') in ['all', 'ebooks'] else 10
$# key ensures the current edition we're on or requested edition are fetched by get_sorted_editions
$ keys = (edition and [edition.key]) or (provider and provider.get_olids(selected_id))
$if ebooks_only:
  $ editions = work.get_sorted_editions(ebooks_only=ebooks_only, limit=editions_limit, keys=keys)
$if not editions:
  $# use ebooks_only to determine whether to lazyload editions table
  $ ebooks_only = False
  $ editions = work.get_sorted_editions(limit=editions_limit, keys=keys)
$ availabilities = {e.availability.get('identifier'): e.availability for e in editions}
$ component_times['get_sorted_editions'] = time() - component_times['get_sorted_editions']

$# This collects which books are previewable in any manner
$ previews = [e for e in editions if e.get('ocaid')]

$# Choose an edition to render
$if editions and not edition:
  $# We're presumably on a work url
  $# edition selection strategy (e.g. language, by id, first w/ ocaid)
  $if provider:
    $ edition = next((e for e in editions if selected_id in provider.get_identifiers(e)), editions[0])
  $else:
    $ edition, provider = get_best_edition(editions)

$# Just in case edition is not set, treat as work
$ edition = edition or page
$ is_editionless_work = edition.type != '/type/edition'

$if not edition.get('availability'):
  $ edition['availability'] = edition.get('ocaid') and availabilities.get(edition['ocaid']) or {}
$ ocaid = edition.get('ocaid')
$ book_title = edition.get('title', '') or (work.title if work else '')
$ work_title = work.title if work else edition.get('title', '')
$ book_subtitle = edition.get('subtitle', '')
$ authors = work.get_authors() if work else edition.get_authors()
$# Only display the first / primary author
$ title_suffix = "by " + authors[0].name if authors else ""
$ title = book_title + " " + title_suffix
$ title_with_site = _("%(page_title)s | Open Library", page_title=title)
$ meta_cover_url = item_image((edition or work).get_cover_url("L"), default="https://openlibrary.org/images/icons/avatar_book-sm.png")
$ _x = ctx.setdefault('cssfile', 'book')

$var title: $title

$code:
    def has_any(*keys):
        return any(edition[k] for k in keys)

$code:
    def get_description(book):
        if book.publishers and book.publish_date:
            ed_info = book.publish_date + ', ' + ', '.join(book.publishers)
        elif book.publish_date:
            ed_info = book.publish_date
        elif book.publishers:
            ed_info = ', '.join(book.publishers)
        else:
            ed_info = 'unknown'

        title = cond(work, work.title, book.title)
        authors = cond(work, work and work.get_authors(), book.get_authors())
        author_info = " by " + ", ".join(a.name or "Unknown author" for a in authors)

        format = ""
        if book.physical_format:
            format += book.physical_format.replace('[', '').replace(']', '')

        if book.languages:
            format += ' in ' + ', '.join(lang.name for lang in book.languages)
        if book.edition_name:
            format += " - " + book.edition_name

        meta = title + author_info + ", " + ed_info + " edition, " + format
        return meta
    description = get_description(page)
    putctx("description", description)

$def display_value(label, value, itemprop=None):
    $if value:
        <dt>$label</dt>
        $if itemprop:
            <dd itemprop="$itemprop" class="object">$:thingrepr(value)</dd>
        $else:
            <dd class="object">$:thingrepr(value)</dd>

$def display_identifiers(label, ids, itemprop=None):
    $if label != "Goodreads":
        $ all_ids = [-1!=id['value'].find('openlib-') for id in ids]
        $if (True in all_ids) and (1==len(all_ids)):
            $return

        $# FIXME: Identifier names need to be translated (I18N)
        <dt>$label</dt>
        <dd class="object" $:cond(itemprop, 'itemprop="%s"' % itemprop, '')>
            $for id in ids:
                $ sep = cond(loop.last, "", ", ")
                $if -1 != id.value.find('openlib-'):
                    $continue
                $if id.url:
                    <a href="$id.url$('?tag=' + affiliate_id('amazon') if 'amazon.' in id.url else '')">$id.value</a>$sep
                $else:
                    ${id.value}$sep
        </dd>

$def display_goodreads(label, ids):
    $if label == "Goodreads":
        <dt>$label</dt>
        $for id in ids:
            <dd><a href="$id.url">$id.value</a></dd>

$:macros.Metatags(title=title_with_site, image=meta_cover_url, description=description)
$set_share_links(url=request.canonical_url, title=title, view_context=ctx)

$if is_privileged_user:
  $:render_template("type/edition/admin_bar", work, edition, ocaid)

$ component_times['ReadlogStats'] = time()
$ star_ratings_stats = macros.StarRatingsStats(work)
$ star_ratings_stats_mobile = macros.StarRatingsStats(work, mobile=True)
$ component_times['ReadlogStats'] = time() - component_times['ReadlogStats']

$ component_times['get_observation_metrics'] = time()
$ reader_observations = get_observation_metrics(work['key']) if show_observations else {}
$ component_times['get_observation_metrics'] = time() - component_times['get_observation_metrics']

$ component_times['affiliate_links component'] = time()
$ prices = edition.key.startswith('/books/')

$ oclc_numbers = (edition.oclc_numbers and edition.oclc_numbers[0]) or ""
$ isbn_13 = edition.get_isbn13() or None
$ isbn_10 = edition.get_isbn10() or None

$ asin = None
$if edition.get('identifiers'):
    $if edition.identifiers.get('amazon'):
        $ asin = edition.identifiers.amazon[0]

$if isbn_10 and not asin:
    $ asin = isbn_10

$ affiliate_links = macros.AffiliateLinks(edition.title, {'isbn': isbn_13, 'asin': asin, 'prices': prices}, async_load=True)
$ component_times['affiliate_links component'] = time() - component_times['affiliate_links component']

$ worldcat_links = macros.WorldcatLink(isbn=isbn_13 or isbn_10, oclc_numbers=oclc_numbers, referer=page.url(relative=False))

<div id="contentBody" role="main" itemscope itemtype="https://schema.org/Book">
  <div class="workDetails">
    $if work and work.key:
        <link itemprop="exampleOfWork" href="$work.key">

    <!-- (mobile only) -->
    $:macros.EditionNavBar(reader_observations, work.edition_count, show_observations)
    <a id="overview-mobile" name="overview-mobile" class="section-anchor section-anchor--no-height"></a>
    $:render_template("type/edition/title_and_author", page, work, edition, ocaid, work_title, star_ratings_stats_mobile, for_desktop=False)
    <div class="editionCover">
      $:macros.databarWork(edition or work, worldcat_links, affiliate_links, editions_page=True, render_times=component_times)
    </div>

    <div class="editionAbout">
      $:macros.EditionNavBar(reader_observations, work.edition_count, show_observations, desktop_only=True)
      <div class="editionAll">
        $ component_times['EditTopbar'] = time()
        $:macros.databarView(page, edition)
        $ component_times['EditTopbar'] = time() - component_times['EditTopbar']
      </div>
      <a id="overview" name="overview" class="section-anchor section-anchor--no-height"></a>
      <!-- (desktop only) -->
      $:render_template("type/edition/title_and_author", page, work, edition, ocaid, work_title, star_ratings_stats, for_desktop=True)

      $if page.type.key in ["/type/work", "/type/edition", "/type/author"]:
        $if edition and page.type.key in ["/type/work"]:
          $ edit_url = edition.url(suffix="/edit")
        $else:
          $ edit_url = page.url(suffix="/edit")
      $else:
        $ edit_url = page.key + "?m=edit"

      $:render_template("type/edition/compact_title", book_title, edit_url)

      $if work and work.description or edition and edition.description:
        $if edition and edition.description:
          $ overview_desc = edition.description
        $else:
          $ overview_desc = work.description
        <div class="book-description read-more">
            <div class="read-more__content" style="max-height:81px">
                $:sanitize(format(overview_desc))
            </div>
            $:macros.ReadMore()
        </div>
      $elif edition:
        <div class="book-description">
            <div class="book-description-content">
                <p class="workHelp">
                    $if page_type=="works":
                      $:_("This work doesn't have a description yet. Can you <b><a href='%(url)s'>add one</a></b>?", url=edition.url('/edit')+"#about/about")
                    $else:
                      $:_("This edition doesn't have a description yet. Can you <b><a href='%(url)s'>add one</a></b>?", url=edition.url('/edit')+"#edition/description")
                </p>
            </div>
        </div>
      <div>
        $if edition:
          <div class="edition-omniline">
            $if edition.publish_date:
              <div class="edition-omniline-item">
                <div>$_("Publish Date")</div>
                <span itemprop="datePublished">$edition.publish_date</span>
              </div>
            $if edition.publishers:
              <div class="edition-omniline-item">
                <div>$_("Publisher")</div>
                <span>
                $for p in edition.publishers:
                  $if "publishers" in ctx.features:
                    <a itemprop="publisher" href="/publishers/$p.replace(' ', '_')"
                       title="$_('Show other books from %(publisher)s', publisher=p)"
                       >$p</a>$cond(loop.last, "", ", ")
                  $else:
                    <a itemprop="publisher" href="/search?publisher_facet=$p.replace('&','%26')"
                       title="$_('Search for other books from %(publisher)s', publisher=p)"
                       >$p</a>$cond(loop.last, "", ", ")
                </span>
              </div>
            $if edition.languages:
              <div class="edition-omniline-item">
                <div class="language">$_("Language")</div>
                <span itemprop="inLanguage">$:thingrepr(edition.languages)</span>
              </div>
            $if edition.number_of_pages:
              <div class="edition-omniline-item">
                <div class="pages">$_("Pages")</div>
                <span class="edition-pages"
                      itemprop="numberOfPages"
                      >$edition.number_of_pages</span>
              </div>
            $if is_librarian:
              $if ocaid:
                <div class="edition-omniline-item">
                 <div>$_("Internet Archive")</div>
                  <span><a href="https://archive.org/details/$ocaid">$ocaid</a></span>
                </div>

              $ edition_identifiers = edition.get_identifiers()
              $ isbns = []
              $for name, values in edition_identifiers.multi_items():
                $if name in ["isbn_10", "isbn_13"]:
                  $for value in values:
                    $isbns.append(value['value'])
              $if isbns:
                <div class="edition-omniline-item">
                  <div>$_("ISBNs")</div>
                  $for isbn in isbns:
                    <span>$isbn</span>
                </div>
          </div>
      </div>

      <div class="Tools">
        <div class="panel mobile-vendor">
          <div class="btn-notice">
            $:worldcat_links

            <div class="cta-section">
              <p class="cta-section-title">$_('Buy this book')</p>
              $:affiliate_links
            </div>
          </div>
        </div>
      </div>

      $ seen = set()
      $if previews and any([len(e.languages) for e in previews]):
        <p class="preview-languages">
          Previews available in:
          $for e in previews:
            $if e.languages[0].name not in seen:
              $ seen.add(e.languages[0].name)
              <a href="$work.key?edition=$(e.ocaid)">$get_language_name(e.languages[0].key)</a>
        </p>

    <div class="subjects">
      <div class="subjects-content">
        $ component_times['SubjectsTags'] = time()
        $:macros.SubjectTags(work, ["Subjects", "People", "Places", "Times"])
        $ component_times['SubjectsTags'] = time() - component_times['SubjectsTags']
      </div>
    </div>

      <a id="editions-list" name="editions-list" class="section-anchor"></a>
      <div class="tab-section">
        $ component_times['EditionsTable'] = time()
        $:render_template("type/work/editions_datatable", work, editions=editions, edition=edition, editions_limit=editions_limit)
        $ component_times['EditionsTable'] = time() - component_times['EditionsTable']
      </div>

      <a id="details" name="details" class="section-anchor"></a>
      <div class="tab-section edition-info">
        $if edition:
          <h2 class="details-title" itemprop="name">$_("Book Details")</h2>
          <hr>
          $if edition.first_sentence:
            <div>
              <h3>$_("First Sentence")</h3>
              <p>"$(edition.first_sentence)"</p>
            </div>

          $ table_of_contents = edition.get_table_of_contents()
          $if table_of_contents and len(table_of_contents.entries) > 1:
            <div class="section read-more">
              <h3>$_("Table of Contents")</h3>
              $ component_times['TableOfContents'] = time()
              $:macros.TableOfContents(table_of_contents, ocaid, cls='read-more__content', attrs='style="max-height:350px"')
              $ component_times['TableOfContents'] = time() - component_times['TableOfContents']
              $:macros.ReadMore()
            </div>

          $if edition.notes or edition.publish_places or edition.series or edition.volume or edition.genres or edition.other_titles or edition.copyright_date or edition.translation_of or edition.translated_from:
            <div class="section">
                <h3>$_("Edition Notes")</h3>
                $if edition.notes:
                    <div class="edition-notes">
                    $:format(edition.notes)
                    </div>
                <dl class="meta">
                    $:display_value(_("Published in"), edition.publish_places)
                    $:display_value(_("Series"), edition.series)
                    $:display_value(_("Volume"), edition.volume)
                    $:display_value(_("Genre"), edition.genres)
                    $:display_value(_("Other Titles"), edition.other_titles)
                    $:display_value(_("Copyright Date"), edition.copyright_date)
                    $:display_value(_("Translation Of"), edition.translation_of)
                    $:display_value(_("Translated From"), edition.translated_from)
                </dl>
            </div>

          $ classifications = edition.get_classifications().multi_items()
          $if classifications:
            <div class="section">
                <h3>$_("Classifications")</h3>
                <dl class="meta">
                    $for name, values in classifications:
                        $:display_identifiers(values[0].label, values)
                </dl>
            </div>

          $ links = page.get_links()
          $if links:
            <div id="external-links">
              <h3 class="header">
                <span class="icon download"></span>
                <span class="head">$_('External Links')</span>
              </h3>
              <div class="panel">
                <ul class="booklinks sansserif">
                  $for link in links:
                    <li><a href="$link.url">$link.title</a></li>
                </ul>
              </div>
            </div>

          $ contributors = edition.get('contributors', [])
          $if contributors:
            <div class="section">
              <h3>$_("Contributors")</h3>
              <dl class="meta">
              $for c in contributors:
                    $:display_value(c.role, c.name)
              </dl>
            </div>

          $if has_any("physical_format", "pagination", "physical_dimensions", "weight"):
            <div class="section">
                <h3>$_("The Physical Object")</h3>
                <dl class="meta">
                    $:display_value(_("Format"), edition.physical_format)
                    $:display_value(_("Pagination"), edition.pagination)
                    $:display_value(_("Number of pages"), edition.number_of_pages, itemprop="numberOfPages")
                    $:display_value(_("Dimensions"), edition.physical_dimensions)
                    $:display_value(_("Weight"), edition.weight)
                </dl>
            </div>


          <div class="section">
            <h3>$_("Edition Identifiers")</h3>
            <dl class="meta">
                $:display_identifiers("Open Library", [storage(url=None, value=edition.key.split("/")[-1])])
                $ no_index = edition.get_ia_meta_fields().get('noindex', False)
                $for name, values in edition.get_identifiers().multi_items():
                    $ identifier_label = values[0].label
                    $if not (edition.is_in_private_collection() and identifier_label == 'Internet Archive'):
                        $if is_privileged_user or not (no_index and identifier_label == 'Internet Archive'):
                            $:display_identifiers(identifier_label, values, itemprop=cond(name in ["isbn_10", "isbn_13"], "isbn", None))
            $:display_goodreads("Open Library", [storage(url=None, value=edition.key.split("/")[-1])])
            $for name, values in edition.get_identifiers().multi_items():
                $:display_goodreads(values[0].label, values)
            </dl>
            <h3>$_("Work Identifiers")</h3>
            <dl class="meta">
                $:display_identifiers("Work ID", [storage(url=None, value=work.key.split("/")[-1])])
                $for name, values in work.get_identifiers().multi_items():
                    $ identifier_label = values[0].label
                    $:display_identifiers(identifier_label, values)
            </dl>
          </div>
	  $ source_records = edition.get('source_records')
          $if source_records:
              <div class="section">
              <h3>$_("Source records")</h3>
              $ get_source_html = render_template("history/sources").get_source_html
              $:'<br/>'.join([get_source_html(s) for s in source_records])
              </div>
          $if work:
            $if not work.excerpts and work.first_sentence:
              <h4>$_("First Sentence")</h4>
              <p class="largest" title=$_("First Sentence")><em>"$work.first_sentence"</em></p>

            $if work.description and work.description != overview_desc:
              <h4>$_("Work Description")</h4>
              <div class="work-description read-more">
                <div class="read-more__content" style="max-height:81px">
                  $:sanitize(format(work.description))
                </div>
                $:macros.ReadMore()
              </div>

            $if work.original_languages:
              <div class="sansserif smallest">$_("Original languages")</div>
              $# TODO: Double check that these language names are localized
              $', '.join(lang.name for lang in work.original_languages)<p>

            $if work.excerpts:
              <h4>$_("Excerpts")</h4>
              <div class="section">
                $for excerpt in work.excerpts:
                  <div class="excerpt addReadMore showlesscontent">
                    <div class="text">
                      $for line in excerpt.excerpt.split('\n'):
                        $line<br/>
                    </div>
                    <div class="attribution">
                      $if excerpt.pages:
                        $_("Page %(page)s", page=excerpt.pages),
                      $if excerpt.author:
                        $def excerpt_author_link(): <a href="$excerpt.author.key">$excerpt.author.displayname</a>
                        $:_("added by %(authorlink)s.", authorlink=str(excerpt_author_link()).strip())
                      $else:
                        $_("added anonymously.")
                      $if excerpt.comment:
                        $:format(excerpt.comment)
                    </div>
                  </div>
              </div>

            $if work.links or (work.wikipedia and work.wikipedia.startswith("http")):
              <h4>$:_('Links <span class="gray small sansserif">outside Open Library</span>')</h4>
              <div class="section">
                <ul class="booklinks sansserif">
                $if work.wikipedia and work.wikipedia.startswith("http"):
                  <li><a href="$page.wikipedia">$_('Wikipedia')</a></li>
                $for link in work.links:
                  <li><a href="$link.url">$link.title</a></li>
                </ul>
              </div>
      </div>

      $if show_observations:
        $ component_times['Review component'] = time()
        $:render_template("observations/review_component", work, reader_observations, page.key)
        $ component_times['Review component'] = time() - component_times['Review component']
      <a id="lists-section" class="section-anchor"></a>
      <div class="workFooter tab-section">
        $# pages like /books/ia:foo00bar are fake records created from metadata API.
        $# Adding them to lists doesn't work. Disabling it to avoid any issues.
        $if "lists" in ctx.features and not page.is_fake_record():
          <div class="lists-heading">
            <h2 class="lists-title">$_('Lists')</h2>
            $ has_lists = False
            $if (work and work.get_lists()) or (edition and edition.get_lists()):
              $ has_lists = True
            $if has_lists:
              <a href="$page.url()/lists">$_('See All')</a>
          </div>
          <div class="user-book-options">
            <div class="Tools tools-override">
              $if work and work.key:
                $ component_times['lists widget: WorkListTime'] = time()
                $:render_template("lists/widget", work, include_header=False, include_widget=False)
                $ component_times['lists widget: WorkListTime'] = time() - component_times['lists widget: WorkListTime']
              $if edition and is_editionless_work:
                $ component_times['lists widget: EditionListTime'] = time()
                $:render_template("lists/widget", edition, include_header=False, include_widget=False)
                $ component_times['lists widget: EditionListTime'] = time() - component_times['lists widget: EditionListTime']
              $if not has_lists:
                $_('This work does not appear on any lists.')
            </div>
          </div>
      </div>
      <a id="related-work-carousel" class="section-anchor"></a>
    </div>
  </div>

  $ component_times['RelatedWorksCarousel'] = time()
  <div class="RelatedWorksCarousel" data-workid="$work.key.split('/')[-1]">
    $:macros.LoadingIndicator(_("Loading Related Books"), "carousel-loading")
  </div>
  $ component_times['RelatedWorksCarousel'] = time() -component_times['RelatedWorksCarousel']

  $ component_times['HistoryTable'] = time()
  $:render_template("lib/history", page)
  $ component_times['HistoryTable'] = time() - component_times['HistoryTable']

  $ component_times['TotalTime'] = time() - component_times['TotalTime']

  $if query_param('debug'):
    $:macros.Profile(component_times)

</div>
